/******************************************************
 * Copyright (c) 2012, LIJUN All rights reserved *
 ******************************************************/

/**
 * Event接口
 * @author carlli
 * @encode utf-8
 * @version 1.0
 * @data 2012.9.24
 * @modify
 * -------------------------------------------------------------------
 * 
 * -------------------------------------------------------------------
 * @usage
 * -------------------------------------------------------------------
 *
 * -------------------------------------------------------------------
 */
Smart.define("event", function(S){
    var __event_list = [];
    
    var getEvent = function(){
        var fn = arguments.callee.caller;
        while(fn){
           var arg = fn.arguments[0];
           if(arg){
              if(String(arg.constructor).indexOf('Event') > -1){
                  return arg;
              }
           }
           fn=fn.caller;
        }
        return (window.event || null);
    };
    
    var getListener = function(node, type, fn){
        var list = __event_list;
        var size = list.length;
        var item = null;
        
        for(var i = 0; i < size; i++){
            item = list[i];
            
            if(item["node"] == node && item["type"] == type && item["fn"] == fn){
                return item;
            }
        }
        return null;
    };
    
    var setListener = function(node, type, fn, handler){
        __event_list.push({
            "node" : node,
            "type" : type,
            "fn" : fn,
            "handler" : handler
        });
    };
    
    var removeListener = function(node, type, fn){
        var list = __event_list;
        var size = list.length;
        var item = null;
        
        for(var i = 0; i < size; i++){
            item = list[i];
            
            if(item["node"] == node && item["type"] == type && item["fn"] == fn){
                var e = __event_list.splice(i, 1);
                return e[0];
            }
        }
        return null;
    };
    
    var __event = {
        /**
         * 添加事件
         * @param Node|String node 事件源
         * @param String type 事件类型
         * @param Function fn 事件处理函数
         * @param Boolean capture 是否捕获
         * @param Array args 事件处理函数的参数
         * @param Object context 上下文（this指针），默认为事件源
         */
        on : function(node, type, fn, capture, args, context){
            var __node = S.Node.one(node);
            var __capture = capture || false;
            var __handler = function(e){
                e = getEvent();
                fn.apply((context||__node), [e].concat((args||[])));
            };
            
            var __listener = getListener(node, type, fn);
            
            if(null == __listener){   
            
                setListener(node, type, fn, __handler);
                
                if("addEventListener" in window){
                    __node.addEventListener(type, __handler, __capture);
                }else{
                    __node.attachEvent("on" + type, __handler);
                }
            }
        },
        /**
         * 移除事件
         * @param Node|String node 事件源
         * @param String type 事件类型
         * @param Function fn 事件处理函数
         * @param Boolean capture 是否捕获
         */
        remove : function(node, type, fn, capture){
            var __node = S.Node.one(node);
            var __capture = capture || false;
            var __listener = removeListener(node, type, fn);
            if(null != __listener){            
                if("removeEventListener" in window){
                    __node.removeEventListener(type, __listener.handler, __capture);
                }else{
                    __node.detachEvent("on" + type, __listener.handler);
                }
            }
        },
        /**
         * 阻止默认行为
         */
        preventDefault : function(){
            var e = getEvent();
            
            if(null != e){
                if("preventDefault" in e){
                    e.preventDefault();
                }else{
                    e.returnValue = false;
                }
            }
        },
        /**
         * 阻止事件冒泡
         */
        stopPropagation : function(){
            var e = getEvent();
            
            if(null != e){
                if("stopPropagation" in e){
                    e.stopPropagation();
                }else{
                    e.cancelBubble = true;
                }
            }
        },
        /**
         * 自定义属性data-action委托事件执行
         * @param Node|String node 事件源
         * @param String type 事件类型
         * @param Object o 引用对象，默认为window
         * --------------------------------------------------
         * <tag data-action="action"></tag>
         */
        action : function(node, type, o){
            var __node = S.Node.one(node);
            var __fn = function(e){
                var __cur = (function(currentNode, refNode){
                    refNode = refNode || S.Node.one("body");

                    if(currentNode && 1 === currentNode.nodeType && currentNode != refNode){
                        if(currentNode.getAttribute("data-action")){
                            return currentNode;
                        }else{
                            var p = currentNode.parentNode;
                            if(p){
                                return arguments.callee(p, refNode);
                            }else{
                                return currentNode;
                            }
                        }
                    }
                    return currentNode;
                })((e.target||e.srcElement), this);
                
                var __action = __cur.getAttribute("data-action");
                
                (function exec(e, action, node, o){
                    var _a = action || "";
                    var path = _a.split(".");
                    var len = path.length;
                    var pck = "";
                    
                    for(var i = 0; i < len; i++){
                        pck = path[i];
                        
                        if(pck){
                            if((pck in o) && (o[pck] instanceof Function) && o[pck].apply){
                                o[pck].apply(node, [e]);
                            }else{
                                o = o[pck];
                            }
                        }
                    }
                    o = null;
                    
                })(e, __action, __cur, (o||window)); 
                
                __cur = null; o = null;
            }
            
            this.on(__node, type, __fn, false, [], __node);
        }
        //delegate : function(){}
    };
    
    S.source("Event", __event); 
});